// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;
// import com.alibaba.druid.util.FnvHash;

// import java.util.Collections;
// import java.util.List;

#include "SQLDbLinkExpr.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/FnvHash.h"
#include "../../../utils/instanceof.h"
#include "../statement/SQLColumnDefinition.h"

SQLDbLinkExpr::SQLDbLinkExpr()
{
}

string_ptr SQLDbLinkExpr::getSimpleName()
{
  return dbLink;
}

SQLExpr_ptr SQLDbLinkExpr::getExpr()
{
  return this->expr;
}

void SQLDbLinkExpr::setExpr(SQLExpr_ptr expr)
{
  this->expr = expr;
}

string_ptr  SQLDbLinkExpr::getDbLink()
{
  return this->dbLink;
}

void SQLDbLinkExpr::setDbLink(string_ptr  dbLink)
{
  this->dbLink = dbLink;
}

//@Override
void SQLDbLinkExpr::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLDbLinkExpr)))
  {
    acceptChild(visitor, this->expr);
  }

  visitor->endVisit(SharedObject(SQLDbLinkExpr));
}

//@Override
BOOL_ptr SQLDbLinkExpr::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (this->expr == expr)
  {
    setExpr(target);
    return BOOL::TRUE;
  }
  return BOOL::FALSE;
}

//@Override
SQLObject_list_ptr SQLDbLinkExpr::getChildren()
{
  return std::make_shared<std::list<SQLObject_ptr>>();
}

//@Override
int SQLDbLinkExpr::hashCode()
{
  long value = hashCode64();
  return (int)(value ^ (value >> 32));
}

//@Override
bool SQLDbLinkExpr::equals(Object_ptr obj)
{
  if (this == obj.get())
  {
    return true;
  }
  if (obj == nullptr)
  {
    return false;
  }
  if (getClass() != obj->getClass())
  {
    return false;
  }
  std::shared_ptr<SQLDbLinkExpr> other = std::dynamic_pointer_cast<SQLDbLinkExpr>(obj);
  return this->hashCode64() == other->hashCode64();
}

SQLObject_ptr SQLDbLinkExpr::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLDbLinkExpr>(new SQLDbLinkExpr());
  std::shared_ptr<SQLDbLinkExpr> x = std::dynamic_pointer_cast<SQLDbLinkExpr>(clone_tmp);
  // SQLDbLinkExpr x = new SQLDbLinkExpr();
  if (expr != nullptr)
  {
    x->setExpr(std::dynamic_pointer_cast<SQLExpr>(expr->clone()));
  }
  x->dbLink = dbLink;
  return x;
}

long SQLDbLinkExpr::nameHashCode64()
{
  if (dbLinkHashCode64 == 0 && dbLink != nullptr)
  {
    dbLinkHashCode64 = FnvHash::hashCode64(dbLink);
  }
  return dbLinkHashCode64;
}

//@Override
long SQLDbLinkExpr::hashCode64()
{
  if (hashCode64_ == 0)
  {
    long hash;
    if (instanceof <SQLExpr, SQLName>(expr.get()))
    {
      hash = (std::dynamic_pointer_cast<SQLName>(expr))->hashCode64();

      hash ^= '@';
      hash *= FnvHash::PRIME;
    }
    else if (expr == nullptr)
    {
      hash = FnvHash::BASIC;
    }
    else
    {
      hash = FnvHash::fnv1a_64_lower(expr->toString());

      hash ^= '@';
      hash *= FnvHash::PRIME;
    }
    hash = FnvHash::hashCode64(hash, dbLink);
    hashCode64_ = hash;
  }

  return hashCode64_;
}

//@Override
SQLObject_ptr SQLDbLinkExpr::getResolvedColumn()
{
  return nullptr;
}
